// #include <iostream>
// #include <vector>
// using namespace std;

// int n, k, result;
// vector<vector<int>> valid_cols; // 存储每行有效的列号

// void backtrack(int row, int cnt, int mask)
// {
//     if (row == n)
//     {
//         if (cnt == k)
//             result++;
//         return;
//     }

//     // 不选当前行
//     backtrack(row + 1, cnt, mask);

//     // 尝试选择当前行的所有有效列
//     for (int col : valid_cols[row])
//     {
//         if (!(mask & (1 << col)))
//         { // 检查列是否可用
//             backtrack(row + 1, cnt + 1, mask | (1 << col));
//         }
//     }
// }

// int main()
// {
//     ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

//     while (cin >> n >> k, n != -1 || k != -1)
//     {
//         if (n == -1)
//             break;

//         // 初始化数据结构
//         valid_cols.clear();
//         valid_cols.resize(n);

//         // 预处理有效列
//         for (int i = 0; i < n; ++i)
//         {
//             string row;
//             cin >> row;
//             for (int j = 0; j < n; ++j)
//             {
//                 if (row[j] == '#')
//                 {
//                     valid_cols[i].push_back(j);
//                 }
//             }
//         }

//         // 计算方案数
//         result = 0;
//         backtrack(0, 0, 0);
//         cout << result << "\n";
//     }

//     return 0;
// }

// #include <iostream>
// #include <vector>
// using namespace std;

// int n, k, ans;
// vector<vector<int>> valid_cols; // 存储每行的有效列（棋盘区域）

// // DFS 函数
// void dfs(int row, int cnt, int used_cols)
// {
//     // 终止条件：所有行处理完毕
//     if (row == n)
//     {
//         if (cnt == k)
//             ans++; // 统计合法方案
//         return;
//     }

//     // 剪枝：剩余行数不足以放置剩余棋子
//     if (cnt + (n - row) < k)
//         return;

//     // 情况1：不在当前行放置棋子
//     dfs(row + 1, cnt, used_cols);

//     // 情况2：在当前行放置棋子（遍历所有有效列）
//     for (int col : valid_cols[row])
//     {
//         if (!(used_cols & (1 << col)))
//         {                                                  // 检查列是否已被占用
//             dfs(row + 1, cnt + 1, used_cols | (1 << col)); // 标记列并递归
//         }
//     }
// }

// int main()
// {
//     ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

//     while (cin >> n >> k, n != -1 || k != -1)
//     {
//         if (n == -1)
//             break;

//         // 初始化
//         valid_cols.clear();
//         valid_cols.resize(n);

//         // 预处理每行的有效列
//         for (int i = 0; i < n; ++i)
//         {
//             string s;
//             cin >> s;
//             for (int j = 0; j < n; ++j)
//             {
//                 if (s[j] == '#')
//                 {
//                     valid_cols[i].push_back(j); // 记录有效列
//                 }
//             }
//         }

//         // DFS 计算答案
//         ans = 0;
//         dfs(0, 0, 0);
//         cout << ans << "\n";
//     }

//     return 0;
// }

#include <iostream>
#include <cstring>
using namespace std;
int n, k;
const int N = 20;
int res;
char arr[N][N];
bool st[N];
void dfs(int x, int cnt)
{

    if (cnt == k)
    {
        res++;
        return;
    }
    if (x >= n)
    {
        return;
    }
    // 枚举列
    for (int i = 0; i < n; i++)
    {
        if (!st[i] && arr[x][i] == '#')
        {
            st[i] = true;
            dfs(x + 1, cnt + 1);
            st[i] = false;
        }
    }
    dfs(x + 1, cnt);
}
int main()
{
    while (cin >> n >> k, n != -1 && k != -1)
    {
        for (int i = 0; i < n; i++)
        {
            scanf("%s", arr[i]);
        }
        res = 0;
        dfs(0, 0);
        printf("%d\n", res);
    }
    return 0;
}